/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.message.service.dingtalk.impl;

import cn.hutool.core.io.FileUtil;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.je.common.base.constants.message.WxMessageType;
import com.je.common.base.service.rpc.DocumentInternalRpcService;
import com.je.common.base.util.MessageUtils;
import com.je.common.base.util.StringUtil;
import com.je.message.Push;
import com.je.message.ResultMsgResp;
import com.je.message.exception.MessageSendException;
import com.je.message.service.AbstractThirdPartyPush;
import com.je.message.service.log.LogServiceFactory;
import com.je.message.service.dingtalk.DingTalkMsgService;
import com.je.message.vo.MessageVo;
import com.je.meta.util.SettingHelper;
import com.je.meta.util.setting.Open.OpenDd;
import com.je.message.me.chanjar.dingding.common.api.DdConsts;
import com.je.message.me.chanjar.dingding.common.bean.result.DdMediaUploadResult;
import com.je.message.me.chanjar.dingding.common.exception.DdErrorException;
import com.je.message.me.chanjar.dingding.common.util.http.DingDingTools;
import com.je.message.me.chanjar.dingding.cp.api.DdCpInMemoryConfigStorage;
import com.je.message.me.chanjar.dingding.cp.api.DdCpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

@Service
public class DingTalkMsgServiceImpl extends AbstractThirdPartyPush implements DingTalkMsgService {


    @Autowired
    private DocumentInternalRpcService documentInternalRpcService;

    @Autowired
    private Environment environment;


    /**
     * @param msgVo
     * @return sendBack
     * @throws IOException
     */
    @Override
    public ResultMsgResp send(MessageVo msgVo)  {

        if (WxMessageType.WZ.equals(msgVo.getMsgType())) {
            return sendWz(msgVo.getUserIds(), msgVo.getDeptIds(), msgVo.getContent());
        } else if (WxMessageType.TP.equals(msgVo.getMsgType())) {
            return sendTp(msgVo.getUserIds(), msgVo.getDeptIds(), msgVo.getFileKey(), msgVo.getFileName());
        } else if (WxMessageType.YY.equals(msgVo.getMsgType())) {
            return sendYy(msgVo.getUserIds(), msgVo.getDeptIds(), msgVo.getFileKey(), msgVo.getFileName());
        } else if (WxMessageType.WJ.equals(msgVo.getMsgType())) {
            return sendWj(msgVo.getUserIds(), msgVo.getDeptIds(), msgVo.getFileKey(), msgVo.getFileName());
        } else if (WxMessageType.LJ.equals(msgVo.getMsgType())) {
            return sendLj(msgVo.getUserIds(), msgVo.getDeptIds(), msgVo.getFileKey(), msgVo.getFileName(), msgVo.getTitle(), msgVo.getContent(), msgVo.getUrl());
        } else if (WxMessageType.OA.equals(msgVo.getMsgType())) {
            return sendOa(msgVo.getUserIds(), msgVo.getDeptIds(), msgVo.getUrlPath(), msgVo.getFileName(), msgVo.getUrl(), msgVo.getPcUrl(), msgVo.getButtonText(), msgVo.getBgColor()
                    , msgVo.getListFrom(), msgVo.getRichNum(), msgVo.getRichUnit(), msgVo.getContent(), msgVo.getBodyTitle(), msgVo.getFileCount(), msgVo.getAuthor());
        } else if (WxMessageType.MD.equals(msgVo.getMsgType())) {
            return sendMd(msgVo.getUserIds(), msgVo.getDeptIds(), msgVo.getContent(), msgVo.getTitle());
        } else if (WxMessageType.KP.equals(msgVo.getMsgType())) {
            return sendKp(msgVo.getUserIds(), msgVo.getDeptIds(), msgVo.getTitle(), msgVo.getContent(), msgVo.getBtnOrientation(), msgVo.getBtnJsonList());
        }

        return new ResultMsgResp(9999, MessageUtils.getMessage("message.sendMsgType.notExits"),false);
    }


    @Override
    public ResultMsgResp sendWz(String userIds, String deptIds, String context)  {
        //初始化服务
        DdCpService ddCpService = initWxCpService();
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        //初始化人员
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.WZ, context);
        msgVo.setDeptIds(deptIds);
        OapiMessageCorpconversationAsyncsendV2Request request = buildInfo(msgVo);

        msg.setMsgtype("text");
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        msg.getText().setContent(msgVo.getContent());
        //执行发送  保存消息日志
        return saveLog(msgVo, msg, request, ddCpService);
    }

    @Override
    public ResultMsgResp  sendTp(String userIds, String deptIds, String filePath, String fileName)  {
        //初始化服务
        DdCpService ddCpService = initWxCpService();
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        //初始化人员
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.TP, filePath, fileName);
        msgVo.setDeptIds(deptIds);
        OapiMessageCorpconversationAsyncsendV2Request request = buildInfo(msgVo);

        if (StringUtil.isEmpty(msgVo.getFileKey())) {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }
        File file = documentInternalRpcService.readFile(msgVo.getFileKey());
        InputStream is = FileUtil.getInputStream(file);
        DdMediaUploadResult uploadMediaRes = ddCpService.mediaUpload(DdConsts.MEDIA_IMAGE, msgVo.getFileName(), is);
        if (uploadMediaRes != null) {
            msg.setMsgtype(DdConsts.MEDIA_IMAGE);
            msg.setImage(new OapiMessageCorpconversationAsyncsendV2Request.Image());
            msg.getImage().setMediaId(uploadMediaRes.getMediaId());
        } else {
            throw new MessageSendException(MessageUtils.getMessage("message.file.upload.failed"));
        }

        //执行发送  保存消息日志
        return saveLog(msgVo, msg, request, ddCpService);
    }

    @Override
    public ResultMsgResp sendYy(String userIds, String deptIds, String filePath, String fileName)  {
        //初始化服务
        DdCpService ddCpService = initWxCpService();
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        //初始化人员
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.YY, filePath, fileName);
        msgVo.setDeptIds(deptIds);
        OapiMessageCorpconversationAsyncsendV2Request request = buildInfo(msgVo);

        if (StringUtil.isEmpty(msgVo.getFileKey())) {
            throw new MessageSendException( MessageUtils.getMessage("message.file.upload.failed"));
        }

        File file = documentInternalRpcService.readFile(msgVo.getFileKey());
        InputStream is = FileUtil.getInputStream(file);
        String tempFolder = environment.getProperty("servicecomb.downloads.directory");
        String filePathBody = tempFolder + File.separator + msgVo.getFileName();
        FileUtil.writeFromStream(is, filePathBody);
        DdMediaUploadResult uploadMediaRes = ddCpService.mediaUpload(DdConsts.MEDIA_VOICE, msgVo.getFileName(), is);
        if (uploadMediaRes == null) {
            throw new MessageSendException( MessageUtils.getMessage("message.file.upload.failed"));
        }
        DingDingTools dt = new DingDingTools();
        Long l = null;
        try {
            l = dt.getAmrDuration(file);
        } catch (IOException e) {
            e.printStackTrace();
        }

        msg.setMsgtype(DdConsts.MEDIA_VOICE);
        msg.setVoice(new OapiMessageCorpconversationAsyncsendV2Request.Voice());
        msg.getVoice().setMediaId(uploadMediaRes.getMediaId());
        Long time = l;
        msg.getVoice().setDuration(String.valueOf(time));

        //执行发送  保存消息日志
        return saveLog(msgVo, msg, request, ddCpService);
    }

    @Override
    public ResultMsgResp sendLj(String userIds, String deptIds, String filePath, String fileName, String title, String text, String url)  {
        //初始化服务
        DdCpService ddCpService = initWxCpService();
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        //初始化人员
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.LJ, filePath, fileName, title, text, url);
        msgVo.setDeptIds(deptIds);
        OapiMessageCorpconversationAsyncsendV2Request request = buildInfo(msgVo);

        if (StringUtil.isEmpty(msgVo.getFileKey())) {
            throw new MessageSendException( MessageUtils.getMessage("message.file.upload.failed"));
        }

        File file = documentInternalRpcService.readFile(msgVo.getFileKey());
        InputStream is = FileUtil.getInputStream(file);
        DdMediaUploadResult uploadMediaRes = ddCpService.mediaUpload(DdConsts.MEDIA_IMAGE, msgVo.getFileName(), is);
        if (uploadMediaRes == null) {
            throw new MessageSendException( MessageUtils.getMessage("message.file.upload.failed"));
        }

        msg.setMsgtype(DdConsts.MEDIA_LINK);
        msg.setLink(new OapiMessageCorpconversationAsyncsendV2Request.Link());
        msg.getLink().setTitle(msgVo.getTitle());
        msg.getLink().setText(msgVo.getContent());
        msg.getLink().setMessageUrl(msgVo.getUrl());
        msg.getLink().setPicUrl(uploadMediaRes.getMediaId());

        //执行发送  保存消息日志
        return saveLog(msgVo, msg, request, ddCpService);
    }

    @Override
    public ResultMsgResp sendOa(String userIds, String deptIds, String filePath, String fileName, String url, String pcUrl, String headText, String headColor, List<OapiMessageCorpconversationAsyncsendV2Request.Form> listFrom, String richNum, String richUnit, String bodyContent, String bodyTitle, String fileCount, String author)  {
        //初始化服务
        DdCpService ddCpService = initWxCpService();
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        //初始化人员
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.OA, filePath, fileName, url, pcUrl, headText, headColor, listFrom, richNum, richUnit, bodyContent, bodyTitle, fileCount, author);
        msgVo.setDeptIds(deptIds);
        OapiMessageCorpconversationAsyncsendV2Request request = buildInfo(msgVo);

        DdMediaUploadResult uploadMediaRes = null;
        if (StringUtil.isNotEmpty(msgVo.getFileKey())) {
            File fileBO = documentInternalRpcService.readFile(msgVo.getFileKey());
            InputStream is = FileUtil.getInputStream(fileBO);
            uploadMediaRes = ddCpService.mediaUpload(DdConsts.MEDIA_IMAGE, msgVo.getFileName(), is);
        }
        msg.setOa(new OapiMessageCorpconversationAsyncsendV2Request.OA());
        OapiMessageCorpconversationAsyncsendV2Request.Body body = new OapiMessageCorpconversationAsyncsendV2Request.Body();
        if (uploadMediaRes != null) {
            body.setImage(uploadMediaRes.getMediaId());
        }
        msg.getOa().setHead(new OapiMessageCorpconversationAsyncsendV2Request.Head());
        msg.getOa().setPcMessageUrl(msgVo.getPcUrl());
        msg.getOa().setMessageUrl(msgVo.getMobileUrl());
        msg.getOa().getHead().setText(msgVo.getTitle());
        if (!msgVo.getBgColor().equals("")) {
            msg.getOa().getHead().setBgcolor("100" + msgVo.getBgColor().replace("#", ""));
        }
        body.setForm(msgVo.getListFrom());
        OapiMessageCorpconversationAsyncsendV2Request.Rich rich = new OapiMessageCorpconversationAsyncsendV2Request.Rich();
        rich.setUnit(msgVo.getRichUnit());
        rich.setNum(msgVo.getRichNum());
        body.setRich(rich);
        body.setContent(msgVo.getContent());
        body.setTitle(msgVo.getBodyTitle());
        body.setFileCount(msgVo.getFileCount());
        body.setAuthor(msgVo.getAuthor());
        msg.setMsgtype(DdConsts.OA);
        msg.getOa().setBody(body);

        //执行发送  保存消息日志
        return saveLog(msgVo, msg, request, ddCpService);
    }

    @Override
    public ResultMsgResp sendMd(String userIds, String deptIds, String mdText, String title)  {
        //初始化服务
        DdCpService ddCpService = initWxCpService();
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        //初始化人员
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.MD, mdText, title);
        msgVo.setDeptIds(deptIds);
        OapiMessageCorpconversationAsyncsendV2Request request = buildInfo(msgVo);

        msg.setMsgtype(DdConsts.MARKDOWN);
        msg.setMarkdown(new OapiMessageCorpconversationAsyncsendV2Request.Markdown());
        msg.getMarkdown().setText(msgVo.getContent());
        msg.getMarkdown().setTitle(msgVo.getTitle());

        //执行发送  保存消息日志
        return saveLog(msgVo, msg, request, ddCpService);
    }

    @Override
    public ResultMsgResp sendKp(String userIds, String deptIds, String cardTitle, String content, String btnOrientation, List<OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList> btnJsonList) throws  MessageSendException {
        //初始化服务
        DdCpService ddCpService = initWxCpService();
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        //初始化人员
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.KP, cardTitle, content, btnOrientation, btnJsonList);
        msgVo.setDeptIds(deptIds);
        OapiMessageCorpconversationAsyncsendV2Request request = buildInfo(msgVo);

        msg.setMsgtype(DdConsts.ACTIONCARD);
        msg.setActionCard(new OapiMessageCorpconversationAsyncsendV2Request.ActionCard());
        msg.getActionCard().setTitle(msgVo.getTitle());//通知标题
        msg.getActionCard().setMarkdown(msgVo.getContent());//内容md
        List<OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList> btnlist = msgVo.getBtnJsonList();
        if (btnlist.size() == 1) {
            OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList btn = new OapiMessageCorpconversationAsyncsendV2Request.BtnJsonList();
            btn = btnlist.get(0);
            msg.getActionCard().setSingleTitle(btn.getTitle());//单行按钮
            msg.getActionCard().setSingleUrl(btn.getActionUrl());//单行链接
        } else if (btnlist.size() > 1) {
            msg.getActionCard().setBtnOrientation(msgVo.getBtnOrientation());
            msg.getActionCard().setBtnJsonList(btnlist);
        }

        //执行发送  保存消息日志
        return saveLog(msgVo, msg, request, ddCpService);
    }

    @Override
    public ResultMsgResp sendWj(String userIds, String deptIds, String filePath, String fileName)  {
        //初始化服务
        DdCpService ddCpService = initWxCpService();
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        //初始化人员
        MessageVo msgVo = new MessageVo(userIds, WxMessageType.WJ, filePath, fileName);
        msgVo.setDeptIds(deptIds);
        OapiMessageCorpconversationAsyncsendV2Request request = buildInfo(msgVo);

        if (StringUtil.isEmpty(msgVo.getFileKey())) {
            throw new MessageSendException( MessageUtils.getMessage("message.file.upload.failed"));
        }

        File fileBO = documentInternalRpcService.readFile(msgVo.getFileKey());
        InputStream is = FileUtil.getInputStream(fileBO);
        DdMediaUploadResult uploadMediaRes = ddCpService.mediaUpload(DdConsts.MEDIA_FILE, msgVo.getFileName(), is);
        if (uploadMediaRes == null) {
            throw new MessageSendException( MessageUtils.getMessage("message.file.upload.failed"));
        }

        msg.setMsgtype("file");
        msg.setFile(new OapiMessageCorpconversationAsyncsendV2Request.File());
        msg.getFile().setMediaId(uploadMediaRes.getMediaId());

        //执行发送  保存消息日志
        return saveLog(msgVo, msg, request, ddCpService);
    }

    /**
     *  保存日志信息
     *
     * @return {@link {@link null}}
     */
    private ResultMsgResp saveLog(MessageVo msgVo, OapiMessageCorpconversationAsyncsendV2Request.Msg msg, OapiMessageCorpconversationAsyncsendV2Request request, DdCpService ddCpService)  {

        if (msg == null) {
            msgVo.setErrorMessage("msg构建失败！");
            logger.info("钉钉消息推送失败！");
            LogServiceFactory.newLog(LogServiceFactory.LogTypeEnum.OTHER).saveAllLog(msgVo, Push.DINGTALK);
            return new ResultMsgResp(9999, "", false);
        }
        request.setMsg(msg);
        try {
            ddCpService.messageSend(request);
        } catch (DdErrorException e) {
            e.printStackTrace();
            msgVo.setErrorMessage(e.getMessage());
            throw new MessageSendException(MessageUtils.getMessage("message.message.failed.to.send") + e.getMessage());
        }
        msgVo.setResult("发送成功！");
        LogServiceFactory.newLog(LogServiceFactory.LogTypeEnum.OTHER).saveAllLog(msgVo, Push.DINGTALK);
        return new ResultMsgResp(200, "钉钉消息推送成功", true);
    }

    /**
     *  初始化人员 系统设置信息
     *
     * @return {@link {@link null}}
     */
    private OapiMessageCorpconversationAsyncsendV2Request buildInfo(MessageVo msgVo)  {
        //校验系统设置有没有勾选
        checkService(thirdPartyType.DINGTALK);

        String deptIds = "";
        boolean allUser = false;
        String userIds = msgVo.getUserIds();

        if ("@all".equals(userIds)) {
            allUser = true;
        }
        List<String> ddUserIds = getUserIds(msgVo, thirdPartyType.DINGTALK);
        deptIds = msgVo.getDeptIds();
        Long agentId = null;
        if (StringUtil.isNotEmpty(metaSystemSettingRpcService.requireSettingValue("OPEN_DD_AGENTID"))) {
            agentId = Long.parseLong(metaSystemSettingRpcService.requireSettingValue("OPEN_DD_AGENTID"));
        }

        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setUseridList(ddUserIds.get(0));
        request.setDeptIdList(deptIds);
        request.setAgentId(agentId);
        request.setToAllUser(allUser);
        return request;
    }

    /**
     * 初始化服务类
     *
     * @return
     */
    private DdCpService initWxCpService() {
        DdCpService ddCpService = null;
            DdCpInMemoryConfigStorage config = new DdCpInMemoryConfigStorage();
            OpenDd loginDdConfig = SettingHelper.getOpenDdConfig();
            config.setCorpId(StringUtil.getDefaultValue(loginDdConfig.getAppKey(), ""));
            config.setCorpSecret(StringUtil.getDefaultValue(loginDdConfig.getAppSecret(), ""));
            int agentId = 0;
            if (StringUtil.isNotEmpty(metaSystemSettingRpcService.requireSettingValue("OPEN_DD_AGENTID"))) {
                agentId = Integer.parseInt(metaSystemSettingRpcService.requireSettingValue("OPEN_DD_AGENTID"));
            }
            // 设置钉钉应用ID
            config.setAgentId(agentId);
            ddCpService.setWxCpConfigStorage(config);
        return ddCpService;
    }

}

